package conceptualization;

import java.util.*;
import java.io.*;
import java.math.*;

public class Aggregation {

	static String conPath = "result.txt";
	static String outPath = "agg.txt";
	
	public static void main(String[] args) {
		timeStart();
		Parser p = new Parser();
		p.readInstance();
		
		aggregatioin(p);
		output();
		
		System.out.println(p.info());
	}
	
	
	static HashMap<Integer, ArrayList<Node>> conAgg = new HashMap<Integer, ArrayList<Node>>();
	static void aggregatioin(Parser p) {
		try {
			FileInputStream fis = new FileInputStream(conPath);
			DataInputStream dis = new DataInputStream(fis);
			BufferedReader br = new BufferedReader(new InputStreamReader(dis));
			String line = br.readLine();
			int count = 1;
			while (line != null && !line.equals("")) {
				String[] tmp = line.split("\\t");
				int qIndex = Integer.parseInt(tmp[0]);
				String query = tmp[1];
				int times = Integer.parseInt(tmp[2]);
				int num = Integer.parseInt(tmp[5]);
				
				for (int i = 0; i < num; i++) {
					line = br.readLine();
					tmp = line.split("\\t");
					String instance = tmp[0];
					int instIndex = p.instanceIndex(instance);
					int conIndex = Integer.parseInt(tmp[1]);
					String typical = tmp[2];
					/* build info node, and get node list of certain concept */
					Node infoNode = new Node(qIndex, times, instIndex, typical, query);
					ArrayList<Node> nodeList = getNode(conIndex);
					/* put the info node into its concept list */
					nodeList.add(infoNode);
				}
				if (count % 10000 == 0) {
					System.out.print(count + " q: ");
					time();
				}
				count++;
				line = br.readLine();
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	static ArrayList<Node> getNode(int conIndex) {
		ArrayList<Node> ans = conAgg.get(conIndex);
		if (ans == null) {
			ans = new ArrayList<Node>();
			conAgg.put(conIndex, ans);
		}
		return ans;
	}
	
	static void output() {
		Set<Integer> keySet = conAgg.keySet();
		int count = 1;
		for (Integer conIndex : keySet) {
			ArrayList<Node> infoNode = getNode(conIndex);
			int end = infoNode.size();
			outLine(conIndex + "\t" + end);
			Object[] nodes = infoNode.toArray();
			Arrays.sort(nodes);
			for (int i = 0; i < end; i++) {
				outLine(((Node)nodes[i]).info());
			}
			if (count % 100000 == 0) {
				System.out.print(count + " c out: "); time();
			}
			count++;
		}
		try {
			bw.flush();
			bw.close();
		} catch (IOException e) {
			e.printStackTrace();
		}

	}
	
	static BufferedWriter bw;
	private static void outLine(String line) {
		try {
			if (bw == null) {
				bw = new BufferedWriter(new FileWriter(outPath));
			}
			bw.write(line); bw.newLine();
			bw.flush();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	static long startTimestamp, lastTimestamp;
	public static void timeStart() {
		startTimestamp = System.currentTimeMillis();
		lastTimestamp = startTimestamp;
	}
	public static void time() {
		long now = System.currentTimeMillis();
		System.out.print((now - lastTimestamp)/1000 + "s since last time;  ");
		System.out.println((now - startTimestamp)/1000 + "s since begin;  ");
		lastTimestamp = now;
	}
}

class Node implements Comparable {
	int qIndex, times, insIndex; 
	String typical;
	String query;
	
	Node (int qIndex, int times, int insIndex, String typical, String query) {
		this.qIndex = qIndex;
		this.times = times;
		this.insIndex = insIndex;
		this.typical = typical;
		this.query = query;
	}
	
	public int compareTo(Object o) {
		Node n = (Node) o;
		return n.times - this.times;
	}
	
	public String info() {
		String ans = "";
		ans += qIndex + "\t"
			+  times  + "\t"
			+ insIndex+ "\t"
			+ typical;;
		return ans;
	}
	
	public String toString() {
		return info();
	}
}
